#include <QtGui>
#include <QListWidgetItem>
#include <QtWebKit>

#include "qpsearch.h"
#include "searchdialog.h"

// ---------------------------------------------------------------------------
// QPSearch
// ---------------------------------------------------------------------------
QPSearch::QPSearch(QWidget *parent) :
        QMainWindow(parent)
{
    setContextMenuPolicy(Qt::NoContextMenu);
    this->setWindowTitle("QPSearch (beta)");

    // Create QTabWidget
    tabWidget = new QTabWidget(this);
    tabWidget->setContextMenuPolicy(Qt::NoContextMenu);
    tabWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);

    // Start listening active tab changes
    //QObject::connect(tabWidget, SIGNAL(currentChanged(int)),this, SLOT(activeTabChanged(int)));

    // Use QTabWidget as a central widget
    setCentralWidget(tabWidget);

    QMenuBar* menubar = menuBar();
    menubar->clear();
    menubar->addAction("Enter Search", this, SLOT(enterSearch()));
    menubar->addAction("About QPSearch", this, SLOT(aboutDialog()));

    // Exit Offline Dialog
    QSystemDeviceInfo* deviceInfo = new QSystemDeviceInfo();
    if (deviceInfo->currentProfile() == QSystemDeviceInfo::OfflineProfile)
    {
        QMessageBox::warning(this, tr("Warning"),
                             tr("Your device is in Offline Mode. QPSearch requires internet connection to operate. \nPlease exit and set the device to Normal Mode. Then launch this application again."),
                             QMessageBox::Close);
        QApplication::exit();
    }
}

QPSearch::~QPSearch()
{
}

void QPSearch::activeTabChanged(int index)
{
    // User selected active tab
    buildTabMenuBar(index);
}

void QPSearch::buildTabMenuBar(int index)
{
    // Clear current menu
    QMenuBar* menubar = menuBar();
    menubar->clear();

    // Build new menu into active tab
    switch (index) {
    case 0:
        {
            menubar->addAction("Enter Search", tabWidget->widget(index), SLOT(enterSearch()));
            break;
        }
    default:
        {
            break;
        }
    };
}

void QPSearch::enterSearch()
{
    m_manager = new QNetworkConfigurationManager(this);
    //const bool selectIap = (m_manager->capabilities()& QNetworkConfigurationManager::CanStartAndStopInterfaces);
    QNetworkConfiguration defaultIap = m_manager->defaultConfiguration();
    session = new QNetworkSession(defaultIap,this);
    session->open();
    session->waitForOpened();

    if (session->isOpen())
    {
        this->setWindowTitle("QPSearch (beta)");
        SearchDialog searchDialog("Enter Search Keywords",this);
        tabWidget->clear();

        if (searchDialog.exec() == QDialog::Accepted){
            searchString = searchDialog.searchText();

            // Create QWidgets for the different tabs
            // [1]: Google
            QResultTabWgt* resultTab1 = new QResultTabWgt(QPSearch::Google, tabWidget, searchString);
            tabWidget->addTab(resultTab1,QIcon(":/tiny_red.gif"), "Google");
            // [2]: Yahoo
            QResultTabWgt* resultTab2 = new QResultTabWgt(QPSearch::Yahoo, tabWidget, searchString);
            tabWidget->addTab(resultTab2,QIcon(":/tiny_red.gif"), "Yahoo");
            // [3]: Bing.com
            QResultTabWgt* resultTab3 = new QResultTabWgt(QPSearch::Bing, tabWidget, searchString);
            tabWidget->addTab(resultTab3,QIcon(":/tiny_red.gif"), "Bing.com");

        }else{
            QLabel* noSearchLabel1 = new QLabel("No search result.");
            tabWidget->addTab(noSearchLabel1,tr("Google"));
            QLabel* noSearchLabel2 = new QLabel("No search result.");
            tabWidget->addTab(noSearchLabel2,tr("Yahoo"));
            QLabel* noSearchLabel3 = new QLabel("No search result.");
            tabWidget->addTab(noSearchLabel3,tr("Bing.com"));
        }
    }else{
        QMessageBox::information ( this, "Information", "Network connection is required to access this application" );
        this->setWindowTitle("QPSearch (beta) - Offline");
    }
    if (session)
        session->close();
    if (m_manager)
        delete m_manager ;
}

void QPSearch::aboutDialog()
{
    QMessageBox msgBox;
    msgBox.setWindowTitle(tr("About QPSearch(beta) v1.0.0"));
    msgBox.setText(tr("<center><b>QPSearch</b> stands for Qt Parallel Search Application.<br />"
                      "Search keywords in multiple search engines simultaneously.<br />"
                      "By Euzer Technologies Pvt Ltd<br />"
                      "<a href='www.euzertech.com'>www.euzertech.com</a></center>"));

    msgBox.exec();
}

// ---------------------------------------------------------------------------
// QResultTabWgt
// ---------------------------------------------------------------------------
QResultTabWgt::QResultTabWgt(int searchEngine, QTabWidget *parent, QString searchString) :
        QTabWidget(parent)
{
    this->parentTabWidget = parent;
    this->searchEngine = searchEngine;
    this->searchString = searchString;
    setContextMenuPolicy(Qt::NoContextMenu);

    listWidget = new QListWidget(this);
    listWidget->setContextMenuPolicy(Qt::NoContextMenu);

    // [0] Send HTTP Request
    view = new QWebView(parent);
    QObject::connect(view, SIGNAL(loadFinished(bool)),
                     this, SLOT(finishedSlot()));

    if (searchEngine == QPSearch::Google){
        view->load(QUrl(QString("http://www.google.com/custom?hl=en&q=%1").arg(searchString)));
    }else if (searchEngine == QPSearch::Yahoo){
        view->load(QUrl(QString("http://search.yahoo.com/search?p=%1").arg(searchString)));
    }else if (searchEngine == QPSearch::Bing){
        view->load(QUrl(QString("http://www.bing.com/search?q=%1").arg(searchString)));
    }

    // ![0]
    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->addWidget(listWidget);
    this->setLayout(layout);

    QLabel* noSearchLabel = new QLabel(tr("Searching..."));
    QListWidgetItem* item = new QListWidgetItem();
    item->setToolTip(resultUrl);
    listWidget->addItem(item);
    listWidget->setItemWidget(item,noSearchLabel);

    QObject::connect(listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
                     this, SLOT(openItem(QListWidgetItem*)));

}

QResultTabWgt::~QResultTabWgt()
{
}

void QResultTabWgt::openItem(QListWidgetItem *item)
{
    //QString message = QString("ItemHeight: %1\nListHeight: %2").arg(item->listWidget()->height()).arg(item->listWidget()->height());
    //QMessageBox* messageBox = new QMessageBox(QMessageBox::Information, "QPSearch", message,
    //    QMessageBox::Ok, this);
    //messageBox->exec();
    //delete messageBox;
    //messageBox = 0;
    bool ret = QDesktopServices::openUrl(QUrl(item->toolTip()));
    if (!ret)
        handleErrorInOpen(item);
}

void QResultTabWgt::handleErrorInOpen(QListWidgetItem *item)
{
    Q_UNUSED(item);
    QMessageBox::warning(this, tr("Operation Failed"), tr("Unkown error!"), QMessageBox::Close);
}

void QResultTabWgt::finishedSlot()
{
    // 1. Remove the initialised item
    if (listWidget->count() == 1){
        listWidget->takeItem(0);
    }

    // 2. Insert search results one by one
    QWebElementCollection elements = view->page()->mainFrame()->findAllElements("div");
    foreach (QWebElement allDivElement, elements)
    {
        bool hasResultItem = false;
        resultTitle = "";
        resultUrl = "";
        resultDesc = "";

        if (searchEngine == QPSearch::Google){
            // [1]: Google
            this->parentTabWidget->setTabIcon(0,QIcon());
            resultUrl = "http://www.google.com";
            if (allDivElement.attribute("class") == "g")
            {
                QWebElement titleAnchorElement = allDivElement.findFirst("h2").findFirst("a");
                if (titleAnchorElement.attribute("class") == "l")
                {
                    resultTitle = QString(titleAnchorElement.toPlainText());
                    resultUrl = titleAnchorElement.attribute("href");
                    hasResultItem = true;
                }
                QWebElement descDivElement = allDivElement.findFirst("table");
                resultDesc = descDivElement.toPlainText();
            }
            // ![1]
        }else if (searchEngine == QPSearch::Yahoo){
            // [2]: Yahoo
            this->parentTabWidget->setTabIcon(1,QIcon());
            resultUrl = "http://www.yahoo.com";
            if (allDivElement.attribute("class") == "res")
            {
                QWebElement titleAnchorElement = allDivElement.findFirst("h3").findFirst("a");
                if (titleAnchorElement.attribute("class") == "yschttl spt")
                {
                    resultTitle = QString(titleAnchorElement.toPlainText());
                    resultUrl = titleAnchorElement.attribute("href");
                    hasResultItem = true;
                }
                QWebElementCollection descDivEleCollection = allDivElement.findAll("div");
                foreach (QWebElement descDivElement, descDivEleCollection)
                {
                    if (descDivElement.attribute("class") == "abstr")
                        resultDesc = descDivElement.toPlainText();
                }
            }
            // ![2]
        }else if (searchEngine == QPSearch::Bing){
            // [3]: Bing.com
            this->parentTabWidget->setTabIcon(2,QIcon());
            resultUrl = "http://www.bing.com";
            if (allDivElement.attribute("class") == "sa_cc")
            {
                QWebElement titleAnchorElement = allDivElement.findFirst("h3").findFirst("a");
                if (titleAnchorElement.attribute("class") == "")
                {
                    resultTitle = QString(titleAnchorElement.toPlainText());
                    resultUrl = titleAnchorElement.attribute("href");
                    hasResultItem = true;
                }
                QWebElement descDivElement = allDivElement.findFirst("p");
                resultDesc = descDivElement.toPlainText();
            }
            // ![3]
        }

        if (hasResultItem)
        {
            QLabel *labelResult = new QLabel();
            QFont serifFont("Times", 14, QFont::Normal);
            labelResult->setFont(serifFont);
            labelResult->setTextFormat(Qt::RichText);
            labelResult->setWordWrap(true);
            labelResult->setAlignment(Qt::AlignTop);
            labelResult->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
            labelResult->setText(
                    QString("<b><u><span style='color:#00A2E8;'>%1</span></u></b><br/><span style='font-size:x-small;'>%2</span><br/><span style='font-size:xx-small;color:#459547;'>%3</span>")
                    .arg(resultTitle).arg(resultDesc).arg(resultUrl));

            QListWidgetItem* item = new QListWidgetItem();
            item->setToolTip(resultUrl);
            listWidget->addItem(item);
            listWidget->setItemWidget(item,labelResult);
            item->setSizeHint(QSize(-1,labelResult->height()));
        }
    }

    // 3. If no search result
    if (listWidget->count() < 1){
        QLabel* noSearchLabel = new QLabel(tr("No search result."));
        QListWidgetItem* item = new QListWidgetItem();
        item->setToolTip(resultUrl);
        listWidget->addItem(item);
        listWidget->setItemWidget(item,noSearchLabel);

        // Hide all loading icons at tab bar
        for (int i = 0;i < parentTabWidget->count(); i++){
            this->parentTabWidget->setTabIcon(i,QIcon());
        }
    }

}

